package com.sentiment.algorithm;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;

import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;

public class LshCoreNo {

	/*
	 * 以下key，blockNumber，linesInblock，signatureLength为四个参数 四个参数均需要不断调试，以获得最佳数值
	 * key： k-shingle的k值大小 ，请取值为3到一句话的平均长度的3/4进行调试
	 * signatureLength：签名长度，根据实际情况取值，如果是一篇文章，值可能需要比较大，但是不要超过80
	 * 严格要求blockNumber*linesInblock=signatureLength blockNumber：桶数目
	 * linesInblock：桶内签名数
	 */
	private int key = 7;
	private int blockNumber = 4;
	private int linesInblock = 2;
	private int signatureLength = 8;

	private int keyContinue;
	private String articShing;
	private int numberOfText;
	private int numberOfSen = 0;
	private String[] artics;
	private String pattern;
	private Matrix signNatureMap;
	private Matrix simMatrix;
	private Matrix pattMatrix;

	private int patternSenFrom;
	private int patternSenTo;
	private ArrayList<SimilarPair> similarPairs = new ArrayList<SimilarPair>();
	private ArrayList<ArrayList<Integer>> pageShingling = new ArrayList<ArrayList<Integer>>();

	private HashMap<Integer, String> bucket = new HashMap<Integer, String>();
	private HashMap<String, Integer> store = new HashMap<String, Integer>();

	private TreeMap<Integer, String> analyMap = new TreeMap<Integer, String>();
	private ArrayList<String> textStructrue = new ArrayList<String>();


	// 启动lsh
	// public void launchLsh(String name) {
	// name = setFilename(name);
	// SelfFile selfFile = new SelfFile();
	// artics = selfFile.ShowDirListPath(ArgumentConf.articlesFilePath);
	// numberOfText = artics.length + 1;
	// pattern = ArgumentConf.PATTERNPATH + name;
	// articShing = ArgumentConf.ARTICLESHING;
	// createTable();
	// minHash();
	// handleLsh();
	// System.out.println(patternSenFrom + ";" + patternSenTo);
	// calSimpagePattToN();
	// System.out.println(signNatureMap);
	// writeToFileSimi(ArgumentConf.similaroutputPath);
	// System.out.println(keyContinue);
	// }

	public void run() {
		minHash();
		handleLsh();
		calSimpagePattToN();
	}

	public String getSentences(String str) {
		str = str.replaceAll("-", "");
		return str.replaceAll("[。！？；]", "-");
	}

	public void setupSignature() {
		signNatureMap = new Matrix(numberOfSen, signatureLength);
		for (int i = 0; i < numberOfSen; i++) {
			for (int j = 0; j < signatureLength; j++) {
				signNatureMap.setNumberWithRowAndCol(i, j, Integer.MAX_VALUE);
			}
		}
	}

	public int hashFuction(int primePoint, int number) {
		// System.out.print(PrimeNumber.number[primePoint]+"*");
		return (PrimeNumber.number[primePoint] * number + 1) % keyContinue;
	}

	public boolean isRightPrime(int primePoint) {
		if ((keyContinue % PrimeNumber.number[primePoint]) == 0) {
			return false;
		}
		return true;
	}

	public void minHash() {
		setupSignature();
		int primePoint = 0;
		int[] indexOfPrime = new int[signatureLength];
		for (int i = 0; i < signatureLength; primePoint++) {
			if (isRightPrime(primePoint)) {
				indexOfPrime[i] = primePoint;
				// System.out.print(primePoint + ",");
				i++;
			}
		}

		for (int i = 0; i < numberOfSen; i++) {
			ArrayList<Integer> arrayList = pageShingling.get(i);
			for (Integer tem : arrayList) {
				for (int j = 0; j < signatureLength; j++) {
					int tempPrime = hashFuction(indexOfPrime[j], tem);
					if (signNatureMap.getNumberWithLineAndRow(i, j) > tempPrime) {
						signNatureMap.setNumberWithRowAndCol(i, j, tempPrime);
					}
				}
			}
		}

	}

	public void createTableSinNo(String pagetext, String textname, int i){

		String structure = "";
		String temp_f = textname;
//		String regex = "^[\\u0020\\u3000]*$";
		String text_buffer = "";
		int tureC = 0;
		int paraCount = 1;
		String[] texts = pagetext.split("\n");
		int temp_i = 0, sl = texts.length;
		while (temp_i < sl) {

			String text = texts[temp_i];
			temp_i++;

			if (text.trim().isEmpty() || "".equals(text.trim())) {
				continue;
			}

			String[] sens = getSentences(text).split("-");

			int senLength = sens.length;
			structure += tureC + ":" + senLength + " ";
			tureC++;

			numberOfSen = numberOfSen + senLength;

			String shingstr;
			String para = "";
			for (int j = 0; j < senLength; j++) {

				int tempJ = j + 1;
				String analys = temp_f + "\t" + paraCount + "\t" + tempJ;
				analyMap.put(numberOfSen - senLength + j, analys);
				String s = sens[j];
				ArrayList<Integer> arrayList = new ArrayList<Integer>();
				int point = 0;
				int count = 0;
				shingstr = "";
				String buffer = "";
				IKSegmenter analyzer = new IKSegmenter(new StringReader(s),true);
                Lexeme le = null;
        		try {
        			while ((le = analyzer.next()) != null){
        				shingstr=le.getLexemeText();
        				if(!store.containsKey(shingstr)){
        					
                            bucket.put(keyContinue,shingstr);
                            store.put(shingstr,keyContinue);
                            buffer = buffer + keyContinue + " ";
                            keyContinue++;
                        } else {
							buffer = buffer + store.get(shingstr) + " ";
						}
        				arrayList.add(store.get(shingstr));
        			}
        		} catch (IOException e) {
        			e.printStackTrace();
        		}
				
				
				para = para + buffer + ".";
				pageShingling.add(arrayList);
			}
			text_buffer = text_buffer + para + "\n";
			paraCount++;
		}
		textStructrue.add(structure);
	
	}
	public void createTableSin(String pagetext, String textname, int i) {
		String structure = "";
		String temp_f = textname;
//		String regex = "^[\\u0020\\u3000]*$";
		String text_buffer = "";
		int tureC = 0;
		int paraCount = 1;
		String[] texts = pagetext.split("\n");
		int temp_i = 0, sl = texts.length;
		while (temp_i < sl) {

			String text = texts[temp_i];
			temp_i++;

			if (text.trim().isEmpty() || "".equals(text.trim())) {
				continue;
			}

			String[] sens = getSentences(text).split("-");

			int senLength = sens.length;
			structure += tureC + ":" + senLength + " ";
			tureC++;

			numberOfSen = numberOfSen + senLength;

			String shingstr;
			String para = "";
			for (int j = 0; j < senLength; j++) {

				int tempJ = j + 1;
				String analys = temp_f + "\t" + paraCount + "\t" + tempJ;
				analyMap.put(numberOfSen - senLength + j, analys);
				String s = sens[j];
				ArrayList<Integer> arrayList = new ArrayList<Integer>();
				int remain = s.length();
				int point = 0;
				int count = 0;
				shingstr = "";
				String buffer = "";
				while (remain >= key) {
					remain--;
					shingstr = shingstr + s.charAt(point);
					count++;

					if (count == key) {
						if (!store.containsKey(shingstr)) {
							bucket.put(keyContinue, shingstr);
							store.put(shingstr, keyContinue);
							buffer = buffer + keyContinue + " ";
							keyContinue++;

						} else {
							buffer = buffer + store.get(shingstr) + " ";
						}
						arrayList.add(store.get(shingstr));
						count = 0;
						shingstr = "";
						point = point - key + 1;
						remain = remain + key - 1;
					}
					point++;
				}
				if (remain == (key - 1) && point != 0) {

					for (int k = 0; k < key - 1; k++) {
						char ch = s.charAt(point + k);
						shingstr = shingstr + ch;
					}
					if (shingstr != "") {
						if (!store.containsKey(shingstr)) {
							bucket.put(keyContinue, shingstr);
							store.put(shingstr, keyContinue);
							buffer = buffer + keyContinue + " ";
							keyContinue++;
						} else {
							buffer = buffer + store.get(shingstr) + " ";
						}
						arrayList.add(store.get(shingstr));
					}

				}
				para = para + buffer + ".";
				pageShingling.add(arrayList);
			}
			text_buffer = text_buffer + para + "\n";
			paraCount++;
		}
		textStructrue.add(structure);
	}

	public void initsimilarPairs() {
		for (int i = 0; i < blockNumber; i++) {
			SimilarPair similarPair = new SimilarPair(i);
			similarPairs.add(similarPair);
		}
	}

	public void calSimpagePattToN() {
		pattMatrix = new Matrix(patternSenTo - patternSenFrom + 1, numberOfSen - patternSenTo + patternSenFrom - 1);
		System.out.println(pattMatrix.getRows() + ";" + pattMatrix.getCols());
		for (int i = 0; i < blockNumber; i++) {
			SimilarPair similarPair = similarPairs.get(i);
			Iterator it = similarPair.getCandidatePair().keySet().iterator();
			while (it.hasNext()) {
				ArrayList<Integer> arrayList = similarPair.getCandidatePair().get(it.next());
				int[] arr = new int[arrayList.size()];
				for (int ie = 0; ie < arrayList.size(); ie++) {
					arr[ie] = arrayList.get(ie);
				}
				for (int k = 0; k < arr.length; k++) {
					for (int h = k + 1; h < arr.length; h++) {
						if (arr[k] >= patternSenFrom && arr[h] < patternSenFrom) {
							pattMatrix.setNumberWithRowAndCol(arr[k] - patternSenFrom, arr[h],
									(int) (signNatureMap.calSimilarCore(arr[k], arr[h]) * 100));
						}
						if (arr[h] >= patternSenFrom && arr[k] < patternSenFrom) {

							pattMatrix.setNumberWithRowAndCol(arr[h] - patternSenFrom, arr[k],
									(int) (signNatureMap.calSimilarCore(arr[h], arr[k]) * 100));
						}
					}
				}
			}
		}
	}

	public void calSimpageNToN() {
		simMatrix = new Matrix(numberOfSen, numberOfSen);
		for (int i = 0; i < blockNumber; i++) {
			SimilarPair similarPair = similarPairs.get(i);
			Iterator it = similarPair.getCandidatePair().keySet().iterator();
			while (it.hasNext()) {
				ArrayList<Integer> arrayList = similarPair.getCandidatePair().get(it.next());
				int[] arr = new int[arrayList.size()];
				for (int ie = 0; ie < arrayList.size(); ie++) {
					arr[ie] = arrayList.get(ie);
				}
				for (int k = 0; k < arr.length; k++) {
					for (int h = k + 1; h < arr.length; h++) {
						simMatrix.setNumberWithRowAndCol(arr[k], arr[h],
								(int) (signNatureMap.calSimilarCore(arr[k], arr[h]) * 100));
					}
				}
			}
		}
	}

	public void handleLsh() {
		initsimilarPairs();

		for (int i = 0; i < numberOfSen; i++) {

			for (int j = 0; j < blockNumber; j++) {
				String str = "";
				for (int k = 0; k < linesInblock; k++) {
					str = str + signNatureMap.getNumberWithLineAndRow(i, j * linesInblock + k);
				}
				if (!similarPairs.get(j).getCandidatePair().containsKey(str)) {
					TreeMap<String, ArrayList<Integer>> treeMap = similarPairs.get(j).getCandidatePair();
					ArrayList<Integer> integerArrayList = new ArrayList<Integer>();
					integerArrayList.add(i);
					treeMap.put(str, integerArrayList);
					similarPairs.get(j).setCandidatePair(treeMap);
					// System.out.println(str+","+i);
				} else {

					ArrayList<Integer> arrayList = similarPairs.get(j).getCandidatePair().get(str);
					arrayList.add(i);
					similarPairs.get(j).getCandidatePair().put(str, arrayList);
					// System.out.println(str+","+i);
				}

			}

		}

	}

	public void createTable() {
		int i;
		String pageText = "", title = "";
		for (i = 0; i < artics.length; i++) {
			createTableSin(pageText, title, i);
		}
		patternSenFrom = numberOfSen;
		createTableSin(pageText, title, i);
		patternSenTo = numberOfSen - 1;
	}

	public String analyticNumberWithArti(int i) {
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(analyMap.get(i));
		return stringBuilder.toString();
	}

	public String writeToDBSimi() {
		StringBuilder sek = new StringBuilder();

		for (int i = 0; i < pattMatrix.getRows(); i++) {
			for (int j = 0; j < pattMatrix.getCols(); j++) {
				if (pattMatrix.getNumberWithLineAndRow(i, j) != 0) {
					StringBuilder stringBuilder = new StringBuilder();
					String[] strapp = analyMap.get(i + patternSenFrom).split("\t");
					// String str=strapp[1];
					// System.out.println(strapp[1]+"\t"+strapp[2]);
					// stringBuilder.append(analyMap.get(i+patternSenFrom));
					stringBuilder.append(strapp[1] + "\t" + strapp[2]);
					stringBuilder.append("\t");
					stringBuilder.append(analyMap.get(j));
					stringBuilder.append("\t");
					stringBuilder.append(pattMatrix.getNumberWithLineAndRow(i, j) + "%");
					sek.append(stringBuilder.toString() + "\n");

				}
			}
		}

		return sek.toString();
	}

	public void writeToFileSimi(String path) {
		try {
			PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter(path)));

			for (int i = 0; i < pattMatrix.getRows(); i++) {
				for (int j = 0; j < pattMatrix.getCols(); j++) {
					if (pattMatrix.getNumberWithLineAndRow(i, j) != 0) {
						StringBuilder stringBuilder = new StringBuilder();
						String[] strapp = analyMap.get(i + patternSenFrom).split("\t");
						// String str=strapp[1];
						// System.out.println(strapp[1]+"\t"+strapp[2]);
						// stringBuilder.append(analyMap.get(i+patternSenFrom));
						stringBuilder.append(strapp[1] + "\t" + strapp[2]);
						stringBuilder.append("\t");
						stringBuilder.append(analyMap.get(j));
						stringBuilder.append("\t");
						stringBuilder.append(pattMatrix.getNumberWithLineAndRow(i, j) + "%");
						output.println(stringBuilder.toString());

					}
				}
			}
			output.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public int getNumberOfText() {
		return numberOfText;
	}

	public void setNumberOfText(int numberOfText) {
		this.numberOfText = numberOfText;
	}

	public int getNumberOfSen() {
		return numberOfSen;
	}

	public void setNumberOfSen(int numberOfSen) {
		this.numberOfSen = numberOfSen;
	}

	public int getPatternSenFrom() {
		return patternSenFrom;
	}

	public void setPatternSenFrom(int patternSenFrom) {
		this.patternSenFrom = patternSenFrom;
	}

	public int getPatternSenTo() {
		return patternSenTo;
	}

	public void setPatternSenTo(int patternSenTo) {
		this.patternSenTo = patternSenTo;
	}

	public static void main(String[] args) {
		// LshCore lshCore=new LshCore();
		// lshCore.loadConfiguration("D:\\xampp\\tomcat\\webapps\\Detection1.1\\src\\minilin.xml");
		// lshCore.articShing="/home/vani/develop/indes";
		// lshCore.createTableSin("/home/vani/develop/indes/1",3);
		// lshCore.createTableSin("/home/vani/develop/indes/2",4);
		// System.out.println(lshCore.textStructrue);
		// lshCore.minHash();
		// System.out.println(lshCore.signNatureMap);
		// lshCore.handleLsh();
		// lshCore.calSimpageNToN();
		// System.out.println(lshCore.simMatrix.tosimilarpair());
		// lshCore.patternSenFrom=3;
		// lshCore.patternSenTo=5;
		// lshCore.calSimpagePattToN();
		// System.out.println(lshCore.pattMatrix.tosimilarpairCore());
		// lshCore.writeToFileSimi("/home/vani/develop/indes/1_0");

	}
}
